#include "StdAfx.h"
#include "KmeansCluster.h"
#include "cv.h"
#include "highgui.h"

CKmeansCluster::CKmeansCluster(void)
{
}

CKmeansCluster::~CKmeansCluster(void)
{
}

BOOL CKmeansCluster::DoCluster(CArray<CPatchSample*>& m_arrFeatures, OUT CArray<int>& clusters)
{
	int iSampleCnt = m_arrFeatures.GetCount();
	if(iSampleCnt == 0)
		return FALSE;

	CvMat* features = cvCreateMat(iSampleCnt, 
		m_arrFeatures[0]->Feature.GetCount(), CV_32F);
	CvMat* cluster = cvCreateMat(iSampleCnt, 1, CV_32SC1);

	for(int i = m_arrFeatures.GetCount() - 1; i >= 0; --i)
	{
		CvMat row;
		cvGetRow(features, &row, i);
		CPatchSample* data = m_arrFeatures[i];
		for(int j = data->Feature.GetCount() - 1; j >= 0; --j)
		{
			cvSetReal1D(&row, j, data->Feature.GetAt(j));
		}
	}

	cvKMeans2(features, ClusterCount, cluster, 
		cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 
		IterationCount, Epsilon));

	ASSERT(cluster->rows == m_arrFeatures.GetCount());

	clusters.RemoveAll();
	for(int i = 0; i < cluster->rows; ++i)
	{
		clusters.Add((int)cvGetReal1D(cluster, i));
	}
	cvReleaseMat(&features);
	cvReleaseMat(&cluster);

	return TRUE;
}
